package com.echo.code.thread.queue.impl;

import com.echo.code.thread.queue.BlockingQueue;
import java.util.LinkedList;
import java.util.logging.Logger;

/**
 * LinkedBlockingQueue Created by baiyap on 2018/9/24.
 */
public class LinkedBlockingQueue<E> implements BlockingQueue<E> {

  public static final int DEFAULT_MAX_LIMIT = 500;
  private static final Logger LOGGER = Logger.getLogger(LinkedBlockingQueue.class.getName());
  private final int limit;
  private final LinkedList<E> queue = new LinkedList<>();

  public LinkedBlockingQueue() {
    limit = DEFAULT_MAX_LIMIT;
  }

  public LinkedBlockingQueue(int limit) {
    this.limit = limit < DEFAULT_MAX_LIMIT ? limit : DEFAULT_MAX_LIMIT;
  }

  @Override
  public void offer(E e) {
    synchronized (queue) {
      while (queue.size() >= limit) {
        LOGGER.info("queue is full, " + getCurrentThreadName() + " suspend, waiting offer...");
        try {
          queue.wait();
        } catch (InterruptedException ite) {
          // TODO
        }
      }
      queue.addLast(e);
      queue.notifyAll();
    }
  }

  @Override
  public E take() {
    synchronized (queue) {
      while (queue.isEmpty()) {
        LOGGER.info("queue is empty, " + getCurrentThreadName() + " suspend, waiting take...");
        try {
          queue.wait();
        } catch (InterruptedException ie) {
          // TODO
        }
      }
      E e = queue.removeFirst();
      queue.notifyAll();
      return e;
    }
  }

  @Override
  public int size() {
    synchronized (queue) {
      return queue.size();
    }
  }
}